package libs.cloak;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.concurrent.Semaphore;

public class Manager {
	
	
	private class Node {
		String name;
		TreeMap<String, Node> childrenMap;
		Handler handler;
	}
	
	
	Node root;
	Semaphore cacheLock;
	TreeMap<String, Object> cache;
	TreeMap<Double, Map.Entry<String, Object>> cacheLRU;
	
	SortedMap<String, String> prefixes;
	
	
	private List<String> vectorizePath(String path)
	{
		List<String> ret = new ArrayList<String>();
		
		StringTokenizer st = new StringTokenizer(path, "/");
		while(st.hasMoreTokens())
		{
			ret.add(st.nextToken());
		}
		
		return ret;
	}
	
	public static Map<String, String> parseAttrMap(String attrs)
	{
		/* For now, rolling my own parser for an attribute map 
		   with the following grammar:
		            
		   STR: std::string | STR\:STR | STR\,STR | STR\\STR | empty_string
		   ATTR: STR:STR
		   ATTRLIST: ATTR,ATTRLIST | ATTR
		
		   These things look like:
		   name:chris,age:21,location:United States,path:/usr/bin\:/home/bin
		 
		   It is a comma separated list of pairs of strings.
		   Each element in the pair is separated by a colon.
		   Backslashes escape those special chars in values.
		   
		   This has been directly copied from the C++ code, with minor
		   modifications for Java
		*/

		
		
		Map<String, String> ret = new TreeMap<String, String>();
		
		boolean gettingName = true;
		String name = "";
		String value = "";
		for(int i=0; i < attrs.length(); i++)
		{
			char ch = attrs.charAt(i);
			if(ch == '\\')
			{
				if(i >= attrs.length() - 1)
					return null;
					//throw Exception(Exception::BADATTR, "BADATTR parseAttrs/2: Attribute syntax is bad, ending with escape character");
				
				i++;
				char es = attrs.charAt(i);
				if(es != ':' && es != ',' && es != '\\')
				{
					return null;
					//throw Exception(Exception::BADATTR, "BADATTR parseAttrs/2: Attribute syntax is bad, unknown escape character");
				}
				else
				{
					if(gettingName)
						name += es;
					else
						value += es;
				}
			}
			else if(ch == ':')
			{
				if(!gettingName)
					return null;
					//throw Exception(Exception::BADATTR, "BADATTR parseAttrs/2: Attribute syntax is bad, unescaped ':' in value");
				else 
					gettingName = false;
			}
			else if(ch == ',')
			{
				if(gettingName)
					return null;
					//throw Exception(Exception::BADATTR, "BADATTR parseAttrs/2: Attribute syntax is bad, no value given before ','");
				else
				{
					ret.put(name, value);
					name = "";
					value = "";
					gettingName = true;
				}
			}
			else
			{
				if(gettingName)
					name += ch;
				else
					value += ch;
			}
		}
		
		// Get last one
		if(name != "")
			ret.put(name,value);
		
		return ret;
	}
	
	public <T> T getEntity(String path, Object attrs)
	{
		List<String> vec = vectorizePath(path);
		String cache_key = path+"{"+attrs.toString()+"}";
		
		try {
			cacheLock.acquire();
		} catch (InterruptedException e) {
			System.err.println("Thread interruption should not happen");
			System.exit(1);
		}
		
		Object obj = cache.get(cache_key);
		
		if(obj != null)
		{
			try
			{
				T ret = (T) obj;
				return ret;
			} catch (ClassCastException e)
			{
				return null;
			}
		}
		
		cacheLock.release();		
		
		// TODO FINISH THIS AND OTHER METHODS
		
	}
	
	public Manager()
	{
		cacheLock = new Semaphore(1);
		cache = new TreeMap<String, Object>();
		cacheLRU = new TreeMap<Double, Map.Entry<String,Object>>();
		
		prefixes = Collections.synchronizedSortedMap(new TreeMap<String, String>());
		
		
	}
	
	public void addPrefix(String key, String prefix)
	{
		prefixes.put(key, prefix);
	}
	
	public String getPrefix(String key)
	{
		return prefixes.get(key);
	}
	
}
